import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class Header {

    private int version;
    private byte[] preHash;
    private byte[] merkleRoot;
    private int time;
    private int bits;
    private int nonce;
    private int height;


    public byte[] serialize() {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            DataOutputStream output = new DataOutputStream(outputStream);
            output.writeInt(version);
            output.write(preHash);
            output.write(merkleRoot);
            output.writeInt(time);
            output.writeInt(bits);
            output.writeInt(nonce);
            return outputStream.toByteArray();
        } catch (Exception e) {
            return null;
        }
    }


    public static Header readHeader(DataInputStream dataInputStream) throws Exception {

        Header header = new Header();
        header.setHeight(dataInputStream.readInt());
        header.setVersion(dataInputStream.readInt());

        byte[] preHash = new byte[32];
        dataInputStream.read(preHash);
        header.setPreHash(preHash);

        byte[] merkleRoot = new byte[32];
        dataInputStream.read(merkleRoot);
        header.setMerkleRoot(merkleRoot);

        header.setTime(dataInputStream.readInt());
        header.setBits(dataInputStream.readInt());
        header.setNonce(dataInputStream.readInt());
        return header;
    }


    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public byte[] getPreHash() {
        return preHash;
    }

    public void setPreHash(byte[] preHash) {
        this.preHash = preHash;
    }

    public byte[] getMerkleRoot() {
        return merkleRoot;
    }

    public void setMerkleRoot(byte[] merkleRoot) {
        this.merkleRoot = merkleRoot;
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public int getBits() {
        return bits;
    }

    public void setBits(int bits) {
        this.bits = bits;
    }

    public int getNonce() {
        return nonce;
    }

    public void setNonce(int nonce) {
        this.nonce = nonce;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }


    @Override
    public String toString() {

        byte[] hash = Hash256.hash(Hash256.hash(serialize()));

        return "Header{" +
                "version=" + version +
                "\n preHash=" + Arrays.toString(preHash) +
                "\n merkleRoot=" + Arrays.toString(merkleRoot) +
                "\n time=" + DateFormatUtil.timeFormat(time) +
                "\n bits=" + bits +
                "\n nonce=" + nonce +
                "\n height=" + height +
                "\n hash=" + Arrays.toString(hash) +
                '}';
    }




}
